#!/usr/bin/env python

import re
from liwe.module import LiweModule
from liwe.tree import Tree
from liwe.utils import UpdatePos

class News ( LiweModule ):
	COUNTER_KIND = {
		'views': 0,
		'prints': 1,
		'comments': 2,
		'clicks': 3,
		'voted': 4,
	}

	NEWS_SEARCH_FIELDS = [ "n.id", "n.id_categ", "n.title", "n.subtitle", "n.id_abstract", "n.id_descr", "n.uid", "n.created", "n.pub_date", "n.visible", "n.id_media", "n.permalink", "n.pos" ]

	def __init__ ( self, liwe ):
		super ( News, self ).__init__ ( liwe, "news" )

		self.dbm = self.liwe.dbm

		# Istanza del Tree per la manipolazione dell'albero
		self.tree = Tree ( liwe )

		self.modules = self.liwe.invoke ( "system.ajax.list_modules" ) [ 'modules' ]
		
		self.upos = UpdatePos ( self.dbm, 'news_news', { 'id' : 'id', 'pos' : 'pos', 'cat': 'id_categ' } )
		
	#=================================================
	# OVERRIDDABLE METHODS
	#=================================================
	#{{{def get_manip ( self, row ):
	def get_manip ( self, row ):
		pass
	#}}}
	#{{{def list_manip ( self, row ):
	def list_manip ( self, row ):
		pass
	#}}}
	#{{{def search_manip ( self, row ):
	def search_manip ( self, row ):
		pass
	#}}}	

	def search_post ( self, rows ):
		return rows

	#{{{def create_manip
	def create_manip ( self, data ):
		pass
	#}}}

	#=================================================
	# PUBLIC
	#=================================================
	#{{{def get ( self, id_news, permalink = '', template_name = 'NEWS_SHOW', admin = 0 ):
	def get ( self, id_news, permalink = '', template_name = 'NEWS_SHOW', admin = 0 ):

		conds = [ "n.id_categ = c.id" ]

		if id_news and id_news > 0:
			conds.append ( "n.id = '%s'" % id_news )

		if permalink:
			conds.append ( "n.permalink = '%s'" % permalink )

		fields = [ "n.id", "n.id_categ", "n.title", "n.subtitle" ,  "n.id_abstract", "n.id_descr", "n.uid", "n.created", "n.pub_date", "n.visible", "n.id_media", "n.pos",
			   "n.url", "n.url_descr", "n.permalink",
			  "c.id AS id_categ", "c.text AS categ" ]
		vals =  self.dbm.single_row ( [ "news_news AS n", "liwe_tree_node AS c" ],
					fields,
					' AND '.join ( conds ) )

		vals [ 'abstract' ] = self.liwe.invoke ( "page_manager.ajax.get", vals [ 'id_abstract' ] ) [ 'page' ] [ 'txt' ]
		vals [ 'descr' ] = self.liwe.invoke ( "page_manager.ajax.get", vals [ 'id_descr' ] ) [ 'page' ] [ 'txt' ]

		#FIXME: se sono in amministrazione non devo aggiornare
		if vals:
			self.dbm.update ( "news_count", { "count" : "*count+1" }, "id_news = '%s' AND kind = %s" % ( id_news, self.COUNTER_KIND [ 'views' ] ) )
			views = self.dbm.single_row ( "news_count", [ "count AS views" ], "id_news = '%s' AND kind = %s" % ( id_news, self.COUNTER_KIND [ 'views' ] ) )
			if views:
				vals [ "views" ] = views [ "views" ]

			tags = self.liwe.invoke ( "tags.ajax.tags_list", id_obj = vals [ "id" ], id_site = self.site_id, module = 'news' )
			vals [ "tags" ] = tags [ "tags" ]

			self._get_media_items ( vals [ 'id' ], vals )

			vals [ '_img' ] = ''
			if vals.get ( 'media' ) and vals [ 'media' ] [ 0 ]:
				media = vals [ 'media' ] [ 0 ]
				vals [ '_img' ] = media [ 'html' ] % { "_size" : "icon", "_ext" : '.jpg'  }

			

		perms = self._get_perms ()
		self._set_admin ( vals, perms )
		self.get_manip ( vals )

		if "_TEMPLATE_NAME" in vals:
			template_name = vals [ '_TEMPLATE_NAME' ]

		vals [ '_html' ] = self.templates.get ( template_name, "NO TEMPLATE FOR: " + template_name + " %s" % vals )

		if not admin:
			#from modules.stats.stats_class import Stats
			#s = Stats ( self.liwe )
			#s.log ( "news", str ( id_news ), "click" )
			self.liwe.invoke ( "stats.ajax.log", module = 'news' , id_ref = id_news, event = "click", uid = self.liwe.session.data.get ( "uid", 0 ) )


		#CERCO FACEBOOK POST ID PAGE ID
		if 'social' in self.modules:
			_list = self.liwe.invoke ( "social.admin.post_list", action_name = 'news', ref_id = id_news ) [ 'list' ]
			fb = ''
			if _list:
				fb = _list [ -1 ]
			vals [ 'fb' ] = fb

		return vals
	#}}}
	#{{{def _get_media_items ( self, id, vals ):
	def _get_media_items ( self, id, vals ):
		res = self.get_media_items ( id, full = True )
		vals [ 'media' ] = res [ 'media_items' ] #self.get_media_items ( vals [ 'id' ] )
		vals [ 'sizes' ] = res [ 'sizes' ] #self.get_media_items ( vals [ 'id' ] )
	#}}}
	#{{{def _get_perms ( self ):
	def _get_perms ( self ):
		uid = self.liwe.pyhp.session.data.get ( "uid", -1 )

		if uid == -1:
			return frozenset ()

		perms = frozenset ( self.liwe.invoke ( "system.ajax.module_get_perms", module_name = "news", uid = uid ) [ 'perms' ] )

		return perms
	#}}}
	#{{{def _set_admin ( self, row, perms ):
	def _set_admin ( self, row, perms ):
		if not 'create' in perms:
			row [ '_admin' ] = ''
			return

		dct = { "_admin_modify" : self.templates [ "ADMIN_MODIFY" ] % {},
			"_admin_del"    : self.templates [ "ADMIN_DEL" ] % {}
		}

		row [ '_admin' ] = self.templates [ 'ADMIN_BAR' ] % dct
	#}}}
	#{{{def get_affinity ( self, id_news ):
	def get_affinity ( self, id_news ):
		# 1. Prendo gli id_tags della news
		tag_objs = self.liwe.invoke ( "tags.ajax.tags_list", id_obj = id_news, id_site = self.site_id, module = 'news', id_only = 1 ) [ 'tags' ]

		# 2. Mi faccio dare gli id_objs delle news affini
		id_objs = self.liwe.invoke ( "tags.ajax.list_affinity", id_obj = id_news, 
					id_site = self.site_id, 
					module = 'news', 
					id_tags = "|".join ( [ str ( t ) for t in tag_objs ] ) ) [ 'affinity_list' ]

		# 3. Prendo i dati base delle news
		news = self.dbm.all_rows ( "news_news AS n", 
					   [ "n.id", "n.title", "subtitle", "n.abstract", "n.created" ], 
					   "n.id IN ( " + ','.join ( id_objs ) + ')', 
					   extras = "ORDER BY n.pub_date DESC LIMIT 5" )

		return news
	#}}}
	#{{{def list ( self, admin = None, mode = "latest", quant = 3, id_categs = '', tags = "", exclude_tags = "", exclude_ids = "", ds_sort = "", ds_cond = "", start_point = 0, do_count = 0 ):
	def list ( self, admin = None, mode = "latest", quant = 3, id_categs = '', tags = "", exclude_tags = "", exclude_ids = "", ds_sort = "", ds_cond = "", start_point = 0, do_count = 0 ):
		conds = []
		tables = [ "news_news AS n" ]

		if not admin:
			conds.append ( "n.visible = 1 AND n.pub_date <= NOW()" )

		if tags or exclude_tags:
			tgs = tags
			tags = self.liwe.invoke ( "tags.ajax.search",
						tag_names = tags.replace ( ",", "|" ),
						id_site = self.site_id, module = 'news', exp = 1,
						exclude_tags = exclude_tags.replace ( ",", "|" ) ) [ 'tags' ]

			#sys.stderr.write ( "********************** %s %s\n" % ( id_categs, tags ) );

			if not tags: return { "rows" : [], "tot_rows" : 0 }
				
			conds.append ( "n.id IN (" + ", ".join ( t [ 'id_obj' ] for t in tags ) + ")" )
		
		if id_categs:
			c_ids = {}
			id_categs = id_categs.split ( "|" );
			for i in id_categs:
				c_ids [ str ( i ) ] = 1
				subt = self.tree.get_subtree ( 'news', i )
				for sub in subt:
					c_ids [ str( sub [ 'id' ] ) ] = 1

			id_categs = c_ids.keys ()
			conds.append ( "n.id_categ IN ( %s )" % ",".join ( id_categs ) )

		if exclude_ids:
			ex_ids = exclude_ids.replace ( "|", "," ).split ( "," )
			conds.append ( "n.id NOT IN (" + ",".join ( ex_ids ) + ")" )

		if ds_cond:
			conds.append ( ds_cond )
		#self.dbm.debug = self.pyhp.log.error

		tot_rows = 0
		if do_count:
			tot_rows = self.dbm.count ( tables, self.NEWS_SEARCH_FIELDS, ' AND '.join ( conds ) )

		sort = ""
		if mode == "latest":
			sort = "ORDER BY n.pub_date DESC"
		elif mode == "sorted":
			sort = "ORDER BY n.title"
		if ds_sort:
			sort = "ORDER BY %s" % ds_sort 

		rows = []
		cur = self.dbm.select ( tables, self.NEWS_SEARCH_FIELDS, ' AND '.join ( conds ), extras = sort + " LIMIT %s,%s" % ( start_point, quant ) )
		if not cur:
			return { "rows" : rows, "tot_rows" : tot_rows }

		perms = self._get_perms ()


		for row in cur:
			#patch per problema rimozione campi a NULL da parte del dbm
			if not row.get ( 'pub_date' ): row [ 'pub_date' ] = ''

			row [ 'categ' ] = ''
			categ = self.tree.get_node ( 'news', row [ 'id_categ' ] )
			if categ: row [ 'categ' ] = categ.get ( 'text' )

			self._get_media_items ( row [ 'id' ], row )

			row [ 'abstract' ] = self.liwe.invoke ( "page_manager.ajax.get", row [ 'id_abstract' ] ) [ 'page' ] [ 'txt' ]
			row [ 'descr' ] = self.liwe.invoke ( "page_manager.ajax.get", row [ 'id_descr' ] ) [ 'page' ] [ 'txt' ]

			self._set_admin ( row, perms )

			self.list_manip ( row )

			row [ '_img' ] = ''
			if row.get ( 'media' ) and row [ 'media' ] [ 0 ]:
				media = row [ 'media' ] [ 0 ]
				row [ '_img' ] = media [ 'html' ] % { "_size" : "icon", "_ext" : '.jpg' }

			rows.append ( row )

		cur.close ()

		return { "rows" : rows, "tot_rows" : tot_rows }
	
	#}}}	
	#{{{def search ( self, title = '', subtitle = '', testo = '', pub_date_start = None, pub_date_end = None, id_categs = '', tags = '', visible = 1, start_pos = 0, limit = 10, exclude_tags = "", ds_sort = "DESC", ds_cond = "", admin = 0 ):
	def search ( self, title = '', subtitle = '', testo = '', pub_date_start = None, pub_date_end = None, id_categs = '', tags = '', visible = 1, start_pos = 0, limit = 10, exclude_tags = "", ds_sort = "DESC", ds_cond = "", admin = 0 ):

		extras = " ORDER BY n.pub_date DESC LIMIT %s,%s " % ( start_pos, limit )
		if ds_sort:
			extras = " ORDER BY %s LIMIT %s,%s " % ( ds_sort, start_pos, limit )
		

		tables = [ "news_news AS n" ]
		fields = self.NEWS_SEARCH_FIELDS

		conds = []

		if not admin: conds = [ "n.pub_date <= NOW()" ]

		tables.append ( "page AS p" )
		conds.append ( "n.id_abstract = p.id_page" )
		fields = fields + [ "p.txt AS abstract" ]

		conds.append ( "visible = %d" % visible )

		if pub_date_start != pub_date_end:
			conds.append ( "n.pub_date BETWEEN ( '%s', '%s' )" % ( pub_date_start, pub_date_end ) )

		if testo:
			ids = []
			pages = self.liwe.invoke ( "page_manager.ajax.search", testo = testo , module = "news", fields = 'id_page' ) [ 'pages' ]
			for p in pages:
				ids.append ( str ( p [ 'id_page' ] ) )

			if ids:
				ids = "(" + ",".join ( ids ) + ")"
				conds.append ( "( n.id_abstract IN %s OR n.id_descr IN %s )" % ( ids, ids ) )
			else:
				return { "rows" : [], "tot_rows" : 0 }

		if title:
			conds.append ( "n.title LIKE '%%%s%%'" % title )

		if subtitle:
			conds.append ( "n.subtitle LIKE '%%%s%%'" % subtitle )
		if tags or exclude_tags:
			tgs = self.liwe.invoke ( "tags.ajax.search", tag_names = tags, id_site = self.site_id, exp = 1, module = "news", exclude_tags = exclude_tags ) [ 'tags' ]


			ids = [ str ( t [ 'id_obj' ] ) for t in tgs ]

			if ids:
				conds.append ( "n.id IN ( %s )" % ",".join ( ids ) )
			else:
				return { "rows" : [], "tot_rows" : 0 }

		if id_categs:
			c_ids = {}
			id_categs = id_categs.split ( "|" );
			for i in id_categs:
				c_ids [ str(i) ] = 1
				subt = self.tree.get_subtree ( 'news', i )
				for sub in subt:
					c_ids [ str( sub [ 'id' ] ) ] = 1

			id_categs = c_ids.keys ()
			conds.append ( "n.id_categ IN ( %s )" % ",".join ( id_categs ) )

		if ds_cond:
			conds.append ( ds_cond )

		conds = " AND ".join ( conds )

		#TODO: aggiornarmento statistiche 

		#FIXME: solo la prima volta
		tot_rows = self.dbm.count ( tables, fields, conds )

		cur = self.dbm.select ( tables, fields, conds, extras = extras )

		news = []

		if cur:
			for n in cur:
				n [ 'categ' ] = ''
				self._get_media_items ( n [ 'id' ], n )
				categ = self.tree.get_node ( 'news', n [ 'id_categ' ] )
				if categ: n [ 'categ' ] = categ.get ( 'text' )
				self.search_manip ( n )
				news.append ( n )

				if not admin:
					#from modules.stats.stats_class import Stats
					#s = Stats ( self.liwe )
					#s.log ( "news", str ( n [ 'id' ] ), "view" )
					self.liwe.invoke ( "stats.ajax.log", module = 'news' , id_ref = n [ 'id' ], event = "view" )
			

			cur.close ()
			#FIX FOR BACK_END
			if not admin: news = self.search_post ( news )

		return { "rows" : news, "tot_rows" : tot_rows }
	#}}}
	#{{{def most_read ( self, limit = 0 ):
	def most_read ( self, limit = 0 ):
		pass
	#}}}
	#{{{def most_commented ( self, limit = 0 ):
	def most_commented ( self, limit = 0 ):
		pass
	#}}}
	#{{{def list_comments ( self, nid ):
	def list_comments ( self, nid ):
		pass
	#}}}

	def sitemap ( self ):
		res = []

		cur = self.dbm.select ( "news_news AS n", 
					     [ "n.id", "n.title" ], 
					     "n.visible = 1 AND n.pub_date <= NOW()",
					     extras = "ORDER BY n.pub_date DESC LIMIT 50000", safe = True )

		if not cur: return res

		for row in cur:
			res.append ( self.sitemap_encode ( loc = self.templates [ "_HREF" ] % row ) )

		return res


	#=================================================
	# ADMIN
	#=================================================
	#{{{def update_pos ( self, id_obj = 0, id_categ = 0, pos = 0 ):
	def update_pos ( self, id_obj = 0, id_categ = 0, pos = 0 ):
		self.upos._update_pos ( id_obj, id_categ, pos )
	#}}}
	#{{{def create ( self, id_categ, title = '', subtitle = '', abstract = '', descr = '', tags = '', visible = 1, id_news = 0, id_media = 0, pub_date = None, permalink = '', url = '', url_descr = '', id_abstract = 0, id_descr = 0, facebook = 0 ):
	def create ( self, id_categ, title = '', subtitle = '', abstract = '', descr = '', tags = '', visible = 1, id_news = 0, id_media = 0, pub_date = None, permalink = '', url = '', url_descr = '', id_abstract = 0, id_descr = 0, facebook = 0 ):
		# Inserisco i dati nel page manager
		id_abstract = self.liwe.invoke ( "page_manager.admin.create", abstract, id_abstract, "news" ) [ 'id_page' ]
		id_descr    = self.liwe.invoke ( "page_manager.admin.create", descr, id_descr, "news" ) [ 'id_page' ]

		uid = self.liwe.pyhp.session.data.get ( "uid", 0 )

		dct = {
			"title": title,
			"subtitle": subtitle,
			"id_abstract": id_abstract,
			"id_descr": id_descr,
			"id_categ": id_categ,
			"visible": visible,
			"id_media": id_media,
			"url" : url,
			"url_descr" : url_descr,
			"permalink" : permalink,
			"pub_date": "*NOW()"
		}

		if pub_date:
			dct [ 'pub_date' ] = pub_date

		data = { "row" : dct, "tags" : tags, "id_news" : id_news }
		self.create_manip ( data )

		tags = data [ 'tags' ]
		dct  = data [ 'row' ]

		if not id_news:
			dct [ 'created' ] = "*NOW()"
			dct [ 'uid' ] = uid

			# insert max pos 
			#self.upos._update_pos ( id_news = id_news, id_categ = dct [ 'id_categ' ] ) 		
			dct [ 'pos' ] = self.upos._find_max_pos ( id_categ = dct [ 'id_categ' ] ) + 1

			self.dbm.insert ( "news_news", dct )
			id_news = self.dbm.insert_id ()
			self._init_count ( id_news )
		else:
			self.dbm.update ( "news_news", dct, "id = %s" % id_news )


		# save tags
		self.liwe.invoke ( "tags.admin.del_all_tags", id_obj = id_news, id_site = self.site_id, module = "news" )
		self.liwe.invoke ( "tags.ajax.tag_object", id_obj = id_news, id_site = self.site_id, tags = tags, module = "news" )
	
		fb_status = 'NO ACTION'
		fb_resp = []
		#FACEBOOK
		if facebook:
			# to bypass html entities in facebook posts - damn charsets!
			# this shouldn't be needed anymore after utf-8 patch
			"""
			import HTMLParser
			h = HTMLParser.HTMLParser ()

			title = h.unescape ( title ).encode ( 'iso-8859-1' )
			subtitle = h.unescape ( subtitle ).encode ( 'iso-8859-1' )
			"""

			_base_url = self.liwe.base_url
		
			_thumb = ''
			res = self.get_media_items ( id_news, full = True )

			media_items = res [ 'media_items' ]
			if media_items:
				_thumb  =  '%s/site/media_manager/image/icon/%s.jpg' % ( _base_url, media_items [ 0 ] [ 'id_media' ] )
						
			_descr = re.sub('<[^<]+?>', '', abstract )

			#FIXME:USARE UN SISTEMA MIGLIORE
			_link = "%s/%s" % ( _base_url, self.get_url ( { "id_news" : id_news, "action" : "get", "title" : title } ) )

			fb_resp = self.liwe.invoke ( "social.admin.post", 'news', id_news, name = title, description = _descr, picture =  _thumb, link = _link, message = subtitle ) 
			

		return { 'id_news' : id_news , 'fb' : fb_resp }
	#}}}
	#{{{def _init_count ( self, id_news ):
	def _init_count ( self, id_news ):
		for v in self.COUNTER_KIND.itervalues():
			self.dbm.insert ( "news_count", { "id_news" : id_news, "kind": v, "count": 0 } )
		
	#}}}
	#{{{def delete ( self, ids ):
	def delete ( self, ids ):
		ids = ids.split ( "|" )
		str_ids = " ,".join ( ids )
		
		for id_news in ids:
			self.upos._update_pos ( id_obj = id_news, pos = -1 )
		self.dbm.delete ( "news_news", "id IN ( %s )" % str_ids )
		self.dbm.delete ( "news_count", "id_news IN ( %s )" % str_ids )

		from modules.media_manager.media_manager_class import MediaManager
		mm  = MediaManager ( self.liwe )

		for id in ids:
			#Cancello i tags della news
			self.liwe.invoke ( "tags.ajax.del_all_tags", id_obj = id, id_site = self.site_id, module = 'news' )

			mm.del_items ( "news", id )

		# TODO: quando ci saranno i commenti e/o voti, cancellare anche quelli
	#}}}
	#{{{def set_categ ( self, text, parent_id = 0, id_node = None, params = '' ):
	def set_categ ( self, text, parent_id = 0, id_node = None, params = '' ):
		uid = self.liwe.pyhp.session.data.get ( "uid", 0 )


		if id_node and int ( id_node ):
			dct = { "text" : text, "params" : params }
			if parent_id: dct [ 'id_parent' ] = parent_id
			
			self.tree.change_attrs ( id_node, dct )
		else:
			id_node = self.tree.add_node ( uid, "news", text, "", id_parent = parent_id, params = params )
			if parent_id:
				self.tree.change_attrs ( parent_id, { 'folder': 1 } )

		return id_node
	#}}}
	#{{{def list_am_categories ( self, start_point = 0, limit = 10 ):
	def list_am_categories ( self, start_point = 0, limit = 10 ):
                tot_rows = 0
                tot_rows = self.dbm.count ( 'liwe_tree_node', [ 'id' ] , "id_parent=0 and section='news'" )
                        
                extra = " LIMIT %s, %s" % ( start_point, limit )
                res = self.dbm.all_rows ( 'liwe_tree_node','*', "id_parent=0 and section ='news'", extras = extra )

                if not res:
                        res = []
                return { "rows" : res, "tot_rows" : tot_rows }
	#}}}
	#{{{def list_am_sub_categories ( self, id_parent, start_point = 0, limit = 10 ):
	def list_am_sub_categories ( self, id_parent, start_point = 0, limit = 10 ):
		if not id_parent :   return { "rows" : [], "tot_rows" : 0 }

                tot_rows = 0
                tot_rows = self.dbm.count ( 'liwe_tree_node', [ 'id' ] , "id_parent=%s and section='news'" % id_parent )
                        
                extra = " LIMIT %s, %s" % ( start_point, limit )
                res = self.dbm.all_rows ( 'liwe_tree_node','*', "id_parent=%s and section ='news'" % id_parent, extras = extra )

                if not res:
                        res = []
                return { "rows" : res, "tot_rows" : tot_rows }
	#}}}
	#{{{def list_categs ( self, id_node = 0 ):
	def list_categs ( self, id_node = 0 ):
		return self.tree.get_all_tree ( 'news', id_node )
	#}}}
	#{{{def get_categ ( self, id_categ ):
	def get_categ ( self, id_categ ):
		return self.tree.get_node ( 'news', id_categ )
	#}}}
	#{{{def del_category ( self, id_categ ):
	def del_category ( self, id_categ ):

		ids = id_categ.split ( '|' )
		id_to_check = ids
		for id in ids:
			lst_subcat = [ str ( x [ 'id' ] ) for x in self.list_categs ( id ) ] ;
			id_to_check += lst_subcat

		tot_news = self.dbm.count ( 'news_news', [ 'id' ] , " id_categ in ( %s ) " % (',').join ( id_to_check  ) )
			
		if ( tot_news ) : 
			self.liwe.set_error ( '1', 'Ci sono %s news legate alla categoria o alle sottocategorie' % tot_news )
			return []

		for id in ids:	
			res = self.tree.del_node ( 'news', id )

		return res
	#}}}

